import axios from "axios";
import type {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosError,
  AxiosResponse,
} from "axios";
import CryptoJS from "crypto-js";
import { useStore } from "@/stores/user";
import router from "@/router";
import { getUrlParamValue } from "@/utils/getUrlParams";
import { someFieldStore } from "@/stores/somefield";

enum RequestEnums {
  TIMEOUT = 20000,
  OVERDUE = 10102, // 登录失效
  FAIL = 999, // 请求失败
  SUCCESS = 200, // 请求成功
}

// 请求响应参数，包含data
interface Result {
  code: number;
  msg: string;
}

interface ResultData<T = any> extends Result {
  data: T;
  page_info: T;
  ext: T;
}

const config = {
  baseURL: "",
  // 设置超时时间
  timeout: RequestEnums.TIMEOUT as number,
  // 跨域时候允许携带凭证
  withCredentials: false,
};

//请求头参数
// 动态导入密钥
const keys = await import("@/config/keys");
const { key_part1, key_part2 } = keys.default;


export class createRequest {
  service: AxiosInstance;
  public constructor(url: string, type?: string) {
    // 实例化axios
    this.service = axios.create(config);

    this.service.interceptors.request.use(
      (config: AxiosRequestConfig): any => {
        const mSomeField = someFieldStore();
        const urlGameId = getUrlParamValue("game_id", mSomeField.clientfields);

        //请求域名
        config.baseURL = import.meta.env.VITE_API_URL + url;

        //拿到了token
        const user = useStore();

        //token
        let token = "";
        if (user.token) {
          token = user.token.user.access_token;
        }

        const game_id =
          // 优先使用config.data中的值
          config.data && typeof config.data.game_id !== "undefined"
            ? config.data.game_id
            : // URL参数安全转换为数字
            urlGameId !== null && !isNaN(Number(urlGameId))
            ? Number(urlGameId)
            : 0; //都没有就用0

        const Gr_Gid = game_id;
        const req_time = Math.floor(Date.now() / 1000);
        const app_key = key_part1 + "#" + Gr_Gid + "#" + key_part2;
        const Gr_Sg = CryptoJS.MD5(app_key + req_time).toString();

        if (!type) {
          config.data = { ...config.data, game_id };
          return {
            ...config,
            headers: {
              Authorization: "Bearer " + token,
              "Content-Type": "application/json",
              "Gr-Gid": game_id,
              "Gr-Ts": req_time,
              "Gr-Sg": Gr_Sg,
            },
          };
        } else {
          //如果是上传图片
          return {
            ...config,
            headers: {
              "Content-Type": "multipart/form-data",
              Authorization: "Bearer " + token,
              "Gr-Gid": game_id,
              "Gr-Ts": req_time,
              "Gr-Sg": Gr_Sg,
            },
          };
        }
      },
      (error: AxiosError) => {
        // 请求报错
        Promise.reject(error);
      }
    );

    //axios拦截
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
        const { data } = response; // 解构

        if (data.code === RequestEnums.OVERDUE) {
          // 登录信息失效，并清空本地的用户状态
          showToast({ message: "登录过期" });
          const user = useStore();
          user.$reset();
          //跳转登录页
          router.push(`/login?redirect=${encodeURIComponent(router.currentRoute.value.fullPath)}`);

          return Promise.reject(data);
        }
        // 全局错误信息拦截（防止下载文件得时候返回数据流，没有code，直接报错）
        if (data.code && data.code !== RequestEnums.SUCCESS && !data["url"]) {
          if (data.code == 24002) {
            showToast({message: "请填写完整" });
          } else {
            console.log(response);
            showToast({ message: data.msg });
          }
          // 此处也可以使用组件提示报错信息
          return Promise.reject(data);
        }
        return data;
      },
      (error: AxiosError) => {
        const { response } = error;
        if (response) {
          this.handleCode(response.status);
        }
        if (!window.navigator.onLine) {
          showToast({message: "网络连接失败" });
        }
      }
    );
  }
  handleCode(code: number): void {
    switch (code) {
      case 401:
        showToast({ message: "登录失败，请重新登录" });
        break;
      default:
        showToast({ message: "请求失败" });
        break;
    }
  }
  // 常用方法封装
  get<T>(url: string, params?: object): Promise<ResultData<T>> {
    return this.service.get(url, { params });
  }
  post<T>(url: string, params?: object): Promise<ResultData<T>> {
    return this.service.post(url, params);
  }
  put<T>(url: string, params?: object): Promise<ResultData<T>> {
    return this.service.put(url, params);
  }
  delete<T>(url: string, params?: object): Promise<ResultData<T>> {
    return this.service.delete(url, { params });
  }
}

export const request = new createRequest("");

export const imgRequest = new createRequest("", "img");
